package com.jmlee.service.impl;

import com.jmlee.bo.OrderItemBO;
import com.jmlee.bo.SubmitOrderBO;
import com.jmlee.enums.OrderStatusEnum;
import com.jmlee.exception.Asserts;
import com.jmlee.mapper.OrderStatusMapper;
import com.jmlee.mapper.OrdersMapper;
import com.jmlee.pojo.*;
import com.jmlee.service.ItemsService;
import com.jmlee.service.OrderItemsService;
import com.jmlee.service.OrderService;
import com.jmlee.service.UserAddressService;
import com.jmlee.util.DateUtil;
import com.jmlee.vo.OrderVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description
 * @Author jmLee
 * @Date 2021/3/11 8:35
 * @Version 1.0
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private ItemsService itemsService;

    @Autowired
    private OrderItemsService orderItemsService;

    @Autowired
    private OrdersMapper ordersMapper;

    @Autowired
    private UserAddressService userAddressService;

    @Autowired
    private OrderStatusMapper orderStatusMapper;

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public CommonResult createOrder(SubmitOrderBO submitOrderBO) {

        // 生成下单商品信息
        List<OrderItemBO> orderItemBOs = submitOrderBO.getOrderItemBOs();

        // 判断订单中的各个商品库存
        for (OrderItemBO orderItemBO : orderItemBOs) {
            Items items = itemsService.getItemsById(orderItemBO.getItemId());

            if (items.getStock() == null || items.getStock() < orderItemBO.getBuyCount()) {
                Asserts.fail("您购买的" + items.getItemName() + "仅剩" + items.getStock() + "件，无法下单");
            }
        }


        // 查询用户收货地址
        UserAddress userAddress = userAddressService.getUserAddressById(submitOrderBO.getAddressId());
        String addr = userAddress.getProvince() + userAddress.getCity() + userAddress.getDistrict() + userAddress.getDetail();
        BigDecimal latitude = userAddress.getLatitude();
        BigDecimal longitude = userAddress.getLongitude();

        Orders newOrder = new Orders();
        newOrder.setUserId(submitOrderBO.getUserId());
        newOrder.setIsComment(0);   // 创建订单时为未评价
        newOrder.setIsDelete(0);    // 订单删除状态
        newOrder.setLeftMsg(submitOrderBO.getLeftMsg());
        newOrder.setPayMethod(submitOrderBO.getPayMethod());
        newOrder.setTotalAmount(submitOrderBO.getOrderTotalPrice());
        newOrder.setRealPayAmount(submitOrderBO.getOrderTotalPrice());
        newOrder.setPostAmount(0);  // 朴朴默认都是包邮的
        newOrder.setReceiverMobile(userAddress.getMobile());
        newOrder.setReceiverAddress(addr);
        newOrder.setReceiverLatitude(latitude);
        newOrder.setReceiverLongitude(longitude);
        newOrder.setReceiverName(userAddress.getReceiver());
        newOrder.setCreatedTime(new Date());
        // 暂时写死数据
        newOrder.setShopId(2L);

        // 生成订单
        ordersMapper.insertOrder(newOrder);
        Long orderId = newOrder.getId();

        // 循环生成订单商品数据，
        for (OrderItemBO orderItemBO : orderItemBOs) {

            OrderItems orderItems = new OrderItems();
            orderItems.setOrderId(orderId);
            orderItems.setItemId(orderItemBO.getItemId());

            // 获取商品信息
            Items items = itemsService.getItemsById(orderItemBO.getItemId());

            // 设置订单商品图片
            orderItems.setItemImg(items.getIcon());
            // 设置订单商品购买数量
            orderItems.setBuyCounts(orderItemBO.getBuyCount());
            // 设置订单商品预计价格
            orderItems.setPrePrice(items.getPriceNormal());
            // 设置订单商品实际价格
            orderItems.setPrice(items.getPriceDiscount());
            // 设置订单商品名称
            orderItems.setItemName(items.getItemName());

            orderItemsService.addOrderItem(orderItems);

            // 扣减库存
            Long updateNum = itemsService.reduceStock(orderItemBO.getItemId(), orderItemBO.getBuyCount());
            if (updateNum <= 0) {
                Asserts.fail("您购买的" + items.getItemName() + "仅剩" + items.getStock() + "件，无法下单");
            }
        }

        // 修改订单状态
        OrderStatus waitPayOrderStatus = new OrderStatus();
        waitPayOrderStatus.setOrderId(orderId);
        waitPayOrderStatus.setOrderStatus(OrderStatusEnum.WAIT_PAY.code);
        waitPayOrderStatus.setCreatedTime(new Date());

        orderStatusMapper.insertOrderStatus(waitPayOrderStatus);

        Map<String,Object> res = new HashMap<>();
        res.put("orderId", orderId);
        res.put("totalAmount",submitOrderBO.getOrderTotalPrice());
        return CommonResult.success(res, "下单成功");
    }


    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void updateOrderStatus(Long orderId, Integer orderStatus) {

        OrderStatus paidStatus = new OrderStatus();
        paidStatus.setOrderId(orderId);
        paidStatus.setOrderStatus(orderStatus);
        paidStatus.setPayTime(new Date());

        orderStatusMapper.updateOrderStatus(paidStatus);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public OrderStatus getOrderStatusInfo(Long orderId) {
        // 查询订单的状态
        return orderStatusMapper.selectByOrderId(orderId);
    }


    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void closeOrder() {

        // 查询所有未付款订单，判断时间是否超时（1天），超时则关闭交易
        OrderStatus queryOrder = new OrderStatus();
        queryOrder.setOrderStatus(OrderStatusEnum.WAIT_PAY.code);

        List<OrderStatus> orderStatusList = orderStatusMapper.selectUnpayOrders(queryOrder);
        if(orderStatusList == null || orderStatusList.isEmpty()) {
            // 未查到未支付的订单，直接返回
            return;
        }

        for (OrderStatus orderStatus : orderStatusList) {
            // 获得订单创建时间
            Date createdTime = orderStatus.getCreatedTime();
            // 和当前时间进行对比
            int days = DateUtil.daysBetween(createdTime, new Date());
            if (days >= 1) {
                // 超过1天，关闭订单
                doCloseOrder(orderStatus.getOrderId());
            }
        }
    }

    @Transactional(propagation = Propagation.REQUIRED)
    void doCloseOrder(Long orderId) {
        OrderStatus closeStatus = new OrderStatus();
        closeStatus.setOrderId(orderId);
        closeStatus.setOrderStatus(OrderStatusEnum.CLOSE.code);
        closeStatus.setCloseTime(new Date());
        orderStatusMapper.updateOrderStatus(closeStatus);

        releaseLockedStock(orderId);
    }


    // 释放超时订单中的商品库存
    @Transactional(propagation = Propagation.REQUIRED)
    void releaseLockedStock(Long orderId) {
        // 查询未支付订单的信息
        OrderVO orderVO = ordersMapper.selectUnpayOrder(orderId);


        List<OrderItems> orderItems = orderVO.getOrderItems();
        for (OrderItems orderItem : orderItems) {
            // 获取商品的购买数量
            Integer buyCounts = orderItem.getBuyCounts();
            Long itemId = orderItem.getItemId();
            itemsService.releaseStock(itemId, buyCounts);
        }
    }

    @Override
    public List<OrderVO> getUserOrders(Long userId, Integer orderStatus) {

        return ordersMapper.selectUserOrder(userId, orderStatus);
    }


    @Override
    public OrderVO getUnpayOrder(Long orderId) {
        // 先去查看下订单的状态是否处于关闭状态
        OrderStatus orderStatus = orderStatusMapper.selectByOrderId(orderId);
        // 如果订单已关闭，则通知前端订单已过期
        if (orderStatus.getCloseTime() != null) {
            return null;
        }
        return ordersMapper.selectUnpayOrder(orderId);
    }

    /**
     * 获取距离用户最近的超市地址
     *
     * @param longitude
     * @param latitude
     * @return
     */
    private Map<String, Object> getShopAxis(double longitude, double latitude) {

        return null;
    }

    // 椭球的长半轴
    private static double EARTH_RADIUS = 6378.137;

    /**
     * 计算弧度
     */
    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    private Map<String, Object> getDistance(double longitude1, double latitude1, double longitude2, double latitude2) {
        double radLat1 = rad(latitude1);
        double radLat2 = rad(latitude2);
        double a = radLat1 - radLat2;
        double b = rad(longitude1) - rad(longitude2);
        double distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        distance = distance * EARTH_RADIUS;
        Map<String, Object> map = new HashMap<String, Object>();
        BigDecimal decimal = new BigDecimal(distance);
        //结果保留2位小数
        distance = decimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        map.put("units", "km");
        map.put("distance", distance);
        return map; // {distance=700.0, units=km}
    }

}
